<?php

class Captchas {

	public $width = 120;
	public $height = 40;
	public $minWordLength = 3;
	public $maxWordLength = 5;
	public $session_var = 'captcha';
	public $backgroundColor = array(255, 255, 255);
	public $colors = array(
		array(27, 78, 181), // blue
		array(22, 163, 35), // green
		array(214, 36, 7), // red
		array(102,102,213), // red
		array(255,91,0), // red
		array(240,0,0), // red
	);
	public $shadowColor = null; //array(0, 0, 0);	

	public $fonts = array(
		'Antykwa' => array('spacing' => -3, 'minSize' => 27, 'maxSize' => 30, 'font' => 'AntykwaBold.ttf'),
		'Candice' => array('spacing' => -1.5, 'minSize' => 28, 'maxSize' => 31, 'font' => 'Candice.ttf'),
		'DingDong' => array('spacing' => -2, 'minSize' => 24, 'maxSize' => 30, 'font' => 'Ding-DongDaddyO.ttf'),
		'Duality' => array('spacing' => -2, 'minSize' => 30, 'maxSize' => 38, 'font' => 'Duality.ttf'),
		'Heineken' => array('spacing' => -2, 'minSize' => 24, 'maxSize' => 34, 'font' => 'Heineken.ttf'),
		'Jura' => array('spacing' => -2, 'minSize' => 28, 'maxSize' => 32, 'font' => 'Jura.ttf'),
		'StayPuft' => array('spacing' => -1.5, 'minSize' => 28, 'maxSize' => 32, 'font' => 'StayPuft.ttf'),
		'Times' => array('spacing' => -2, 'minSize' => 28, 'maxSize' => 34, 'font' => 'TimesNewRomanBold.ttf'),
		'VeraSans' => array('spacing' => -1, 'minSize' => 20, 'maxSize' => 28, 'font' => 'VeraSansBold.ttf'),
	);
	public $Yperiod    = 14;
    public $Yamplitude = 12;
    public $Xperiod    = 10;
    public $Xamplitude = 5;
	//旋转
	public $maxRotation = 8;
	//图像的大小因素（更好的图像质量）1: low, 2: medium, 3: high
	public $scale = 3;
	//模糊效果更好的影像品质（但速度慢图像处理）。更好的图像效果和规模= 3
	public $blur = false;
	public $debug = true;
	public $imageFormat = 'png';
	public $im;

	public function __construct($config = array()){
	}
	public function CreateImage(){
		$ini = microtime(true);		
		//初始化
		$this->ImageAllocate();
		//插入文本
		$text = $this->getRandomText();
		$fontcfg = $this->fonts[array_rand($this->fonts)];
		$this->WriteText($text, $fontcfg);
		$_SESSION[$this->session_var] = $text;

		//转换
		$this->WaveImage();
		if ($this->blur && function_exists('imagefilter')){
			imagefilter($this->im, IMG_FILTER_GAUSSIAN_BLUR);
		}
		$this->ReduceImage();
		/*
		//测试
		if ($this->debug) {
            imagestring($this->im,2,1, $this->height-15,
                " {$fontcfg['font']} ".round((microtime(true)-$ini)*1000)."ms",
                $this->GdFgColor
            );
        }
		
		if ($this->debug) {
            imagestring($this->im,1,59, $this->height-8,"AdminPub.com",
                $this->GdFgColor
            );
        }
		*/

		$this->WriteImage();
		$this->Cleanup();
	}

	protected function ImageAllocate(){
		if (!empty($this->im)){
			imagedestroy($this->im);
		}
		$this->im = imagecreatetruecolor($this->width * $this->scale, $this->height * $this->scale); 
		//背景颜色
		$this->GdBgColor = imagecolorallocate($this->im,
			$this->backgroundColor[0],
			$this->backgroundColor[1],
			$this->backgroundColor[2]
			);
		imagefilledrectangle($this->im, 0, 0, $this->width * $this->scale, $this->height * $this->scale, $this->GdBgColor); 
		//前景颜色
		$color = $this->colors[mt_rand(0, sizeof($this->colors)-1)];
		$this->GdFgColor = imagecolorallocate($this->im, $color[0], $color[1], $color[2]); 
		//阴影颜色
		if (!empty($this->shadowColor) && is_array($this->shadowColor) && sizeof($this->shadowColor) >= 3){
			$this->GdShadowColor = imagecolorallocate(
				$this->im,
				$this->shadowColor[0],
				$this->shadowColor[1],
				$this->shadowColor[2]
			);
		}
	}

	//文本生成
	protected function getRandomText(){
		$code = '';
		$characters = 'abcdefghijklmnopqrstuvwxyz';
		//$length = rand(3,5);
		$length = 4;
		while( strlen($code) < $length ) {
			$code .= substr($characters, rand() % (strlen($characters)),1);
		}
		return $code;		
	}
	

	//文本插入
	protected function WriteText($text, $fontcfg = array()){
		if (empty($fontcfg)){
			// Select the font configuration
			$fontcfg = $this->fonts[array_rand($this->fonts)];
		}
		// Full path of font file
		$fontfile = PUBLIC_PATH.'/fonts/'.$fontcfg['font'];

		/**
		* * Increase font-size for shortest words: 9% for each glyp missing
		*/
		$lettersMissing = $this->maxWordLength - strlen($text);
		$fontSizefactor = 1 + ($lettersMissing * 0.09); 
		//文本生成（由字符字符）
		$x = 20 * $this->scale;
		$y = round(($this->height * 27 / 40) * $this->scale);
		$length = strlen($text);
		for ($i = 0; $i < $length; $i++){
			$degree = rand($this->maxRotation * -1, $this->maxRotation);
			$fontsize = rand($fontcfg['minSize'], $fontcfg['maxSize']) * $this->scale * $fontSizefactor;
			$letter = substr($text, $i, 1);
			if ($this->shadowColor){
				$coords = imagettftext($this->im, $fontsize, $degree,
					$x + $this->scale, $y + $this->scale,
					$this->GdShadowColor, $fontfile, $letter);
			}
			$coords = imagettftext($this->im, $fontsize, $degree,
				$x, $y,
				$this->GdFgColor, $fontfile, $letter);
			$x += ($coords[2] - $x) + ($fontcfg['spacing'] * $this->scale);
		}
	}

	protected function WaveImage(){
		// X轴波的产生
		$xp = $this->scale * $this->Xperiod * rand(1, 3);
		$k = rand(0, 100);
		for ($i = 0; $i < ($this->width * $this->scale); $i++){
			imagecopy($this->im, $this->im,
				$i-1, sin($k + $i / $xp) * ($this->scale * $this->Xamplitude),
				$i, 0, 1, $this->height * $this->scale);
		}
		// Y轴波的产生
		$k = rand(0, 100);
		$yp = $this->scale * $this->Yperiod * rand(1, 2);
		for ($i = 0; $i < ($this->height * $this->scale); $i++){
			imagecopy($this->im, $this->im,
				sin($k + $i / $yp) * ($this->scale * $this->Yamplitude), $i-1,
				0, $i, $this->width * $this->scale, 1);
		}
	}

	//降低图片的最终尺寸
	protected function ReduceImage(){
		$imResampled = imagecreatetruecolor($this->width, $this->height);
		imagecopyresampled($imResampled, $this->im,
			0, 0, 0, 0,
			$this->width, $this->height,
			$this->width * $this->scale, $this->height * $this->scale
			);
		imagedestroy($this->im);
		$this->im = $imResampled;
	}
	
	//生成图像
	protected function WriteImage(){
		if ($this->imageFormat == 'png' && function_exists('imagepng')){
			header("Content-type: image/png");
			imagepng($this->im);
		}else{
			header("Content-type: image/jpeg");
			imagejpeg($this->im, null,90);
		}
	}

	//清除
	protected function Cleanup(){
		imagedestroy($this->im);
	}
}

?>
